/**
 * @ProjectName: 
 * @Copyright: 2014 lisheng  All Right Reserved.
 * @address: toughheart@163.com
 * @date: 2015年4月11日 下午4:50:13
 * @Description: 本内容未经本人允许禁止使用、转发.
 */

package com.ls.fw.web.activiti.base;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;

import org.activiti.engine.FormService;
import org.activiti.engine.HistoryService;
import org.activiti.engine.IdentityService;
import org.activiti.engine.ManagementService;
import org.activiti.engine.ProcessEngine;
import org.activiti.engine.ProcessEngineConfiguration;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.form.FormProperty;
import org.activiti.engine.form.StartFormData;
import org.activiti.engine.form.TaskFormData;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.activiti.engine.task.TaskQuery;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.servlet.ModelAndView;

import com.ls.fw.mvc.springmvc.base.BaseController;
import com.ls.fw.web.activiti.def.TaskType;

/**
 * 
 * @author lisheng
 * @date 2015年4月11日 下午4:50:13
 * @version V1.0
 */
public abstract class BaseActivitiController extends BaseController {

	@Autowired
	protected ProcessEngineConfiguration processEngineConfiguration= null;
	@Autowired
	protected ProcessEngine processEngine = null;
	@Autowired
	protected RepositoryService repositoryService;
	@Autowired
	protected RuntimeService runtimeService;
	@Autowired
	protected TaskService taskService;
	@Autowired
	protected HistoryService historyService;
	@Autowired
	protected IdentityService identityService;
	@Autowired
	protected ManagementService managementService;
	@Autowired
	protected FormService formService;

	public ProcessEngine getProcessEngine() {
		return this.processEngine;
	}

	public void setProcessEngine(ProcessEngine processEngine) {
		this.processEngine = processEngine;
	}

	/**
	 * 读取用户任务的表单字段
	 * 
	 * @author lisheng
	 * @date 2015年4月11日 下午4:56:55
	 * @version V1.0
	 * @param mav
	 * @param taskId
	 * @return
	 * @throws Exception
	 */
	public ModelAndView readTaskForm(ModelAndView mav, String taskId)
			throws Exception {
		TaskFormData taskFormData = formService.getTaskFormData(taskId);
		if (taskFormData.getFormKey() != null) {
			Object renderedTaskForm = formService.getRenderedTaskForm(taskId);
			Task task = taskService.createTaskQuery().taskId(taskId)
					.singleResult();
			mav.addObject("task", task);
			mav.addObject("taskFormData", renderedTaskForm);
			mav.addObject("hasFormKey", true);
		} else {
			mav.addObject("taskFormData", taskFormData);
		}
		return mav;
	}

	/**
	 * 读取用户的任务
	 * 
	 * @author lisheng
	 * @date 2015年4月11日 下午5:09:43
	 * @version V1.0
	 * @param mav
	 * @param userId
	 * @param taskType
	 * @return
	 * @throws Exception
	 */
	public ModelAndView readTasks(ModelAndView mav, String userId,
			TaskType taskType, int firstResult, int maxResults)
			throws Exception {
		List<Task> tasks = null;
		TaskQuery q = taskService.createTaskQuery();
		switch (taskType) {
		case DOING:
			// 读取直接分配给当前人或者已经签收的任务
			q.taskAssignee(userId);
			break;
		case WAITING:
			// 等待签收的任务
			q.taskCandidateUser(userId);
			break;
		case ALL:
			q.taskCandidateOrAssigned(userId);
			break;
		default:
			break;

		}
		tasks = q.listPage(firstResult, maxResults);
		mav.addObject("tasks", tasks);
		return mav;
	}

	/**
	 * 完成任务
	 * 
	 * @author lisheng
	 * @date 2015年4月11日 下午5:15:23
	 * @version V1.0
	 * @param taskId
	 * @param request
	 */
	public void finishTask(String taskId, HttpServletRequest request) {
		TaskFormData taskFormData = formService.getTaskFormData(taskId);
		String formKey = taskFormData.getFormKey();
		// 从请求中获取表单字段的值
		List<FormProperty> formProperties = taskFormData.getFormProperties();
		Map<String, String> formValues = this.getFormValues(formKey, request,
				formProperties);
		formService.submitTaskFormData(taskId, formValues);
	}

	/**
	 * 从请求中获取表单字段的值
	 * 
	 * @author lisheng
	 * @date 2015年4月11日 下午5:23:20
	 * @version V1.0
	 * @param formKey
	 * @param request
	 * @param formProperties
	 * @return
	 */
	protected Map<String, String> getFormValues(String formKey,
			HttpServletRequest request, List<FormProperty> formProperties) {
		// 从请求中获取表单字段的值
		Map<String, String> formValues = new HashMap<String, String>();
		if (StringUtils.isNotBlank(formKey)) { // formkey表单
			Map<String, String[]> parameterMap = request.getParameterMap();
			Set<Entry<String, String[]>> entrySet = parameterMap.entrySet();
			for (Entry<String, String[]> entry : entrySet) {
				String key = entry.getKey();
				formValues.put(key, entry.getValue()[0]);
			}
		} else { // 动态表单
			for (FormProperty formProperty : formProperties) {
				if (formProperty.isWritable()) {
					String value = request.getParameter(formProperty.getId());
					formValues.put(formProperty.getId(), value);
				}
			}
		}
		return formValues;
	}

	/**
	 * 提交表单字段并启动一个新的流程实例
	 * 
	 * @author lisheng
	 * @date 2015年4月11日 下午5:19:48
	 * @version V1.0
	 * @param pdid
	 * @param request
	 * @param userId
	 * @return
	 */
	public ProcessInstance startProcess(String pdid, HttpServletRequest request,
			String userId) {
		ProcessDefinition processDefinition = repositoryService
				.createProcessDefinitionQuery().processDefinitionId(pdid)
				.singleResult();
		boolean hasStartFormKey = processDefinition.hasStartFormKey();
		List<FormProperty> formProperties = null;
		if (hasStartFormKey) { // formkey表单
			StartFormData formData = formService.getStartFormData(pdid);
			// 从请求中获取表单字段的值
			formProperties = formData.getFormProperties();
		}
		Map<String, String> formValues = this.getFormValues(hasStartFormKey
				+ "", request, formProperties);

		identityService.setAuthenticatedUserId(userId);
		// 提交表单字段并启动一个新的流程实例
		ProcessInstance processInstance = formService.submitStartFormData(pdid,
				formValues);
		return processInstance;
	}
}
